package cn.hl.basic.service.impl;

import cn.hl.basic.dto.SmsCodeDto;
import cn.hl.basic.exception.BusinessException;
import cn.hl.basic.service.IVerifyCodeService;
import cn.hl.basic.util.StrUtils;
import cn.hl.basic.util.VerifyCodeUtils;
import cn.hl.user.domain.User;
import cn.hl.user.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.util.concurrent.TimeUnit;

@Service
public class VerifyCodeServiceImpl implements IVerifyCodeService {

    @Autowired
    @Qualifier("redisTemplate")
    private RedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private JavaMailSender javaMailSender;

    @Override
    public String getImageCode(String key) {
        // 使用工具类获取图形验证码
        String code = StrUtils.getComplexRandomString(4);
        // 将图形验证码保存到Redis中
        redisTemplate.opsForValue().set(key, code,5, TimeUnit.MINUTES);
        // 使用工具类将获取的图形验证码编译为base64的字符串
        String verifyCode = VerifyCodeUtils.verifyCode(100, 40, code);
        // 返回
        return verifyCode;
    }

    @Override
    public void smsCode(SmsCodeDto smsCodeDto) {
        // 1.校验是否为空
        String phone = smsCodeDto.getPhone();
        String imageCode = smsCodeDto.getImageCode();
        String imageCodeKey = smsCodeDto.getImageCodeKey();

        if (StringUtils.isEmpty(phone)) {
            throw new BusinessException("电话号码不能为空！");
        }
        if (StringUtils.isEmpty(imageCode)) {
            throw new BusinessException("图片验证码不能为空！");
        }
        // 2.校验图形验证码是否过期，是否正确
        Object o = redisTemplate.opsForValue().get(imageCodeKey);
        if (o== null) {
            throw new BusinessException("图形验证码已经过期，请重新获取图形验证码！");
        }
        if (!o.toString().equalsIgnoreCase(imageCode)) {
            throw new BusinessException("图形验证码错误！");
        }
        // 3.校验手机号码是否注册过
        User user = userMapper.findByPhone(phone);
        if (user != null) {
            throw new BusinessException("手机号码已被注册，请直接登录！");
        }
        // 4.获取手机验证码
        Object code = redisTemplate.opsForValue().get("register:" + phone);
        String smsCode = null;
        // 4.1手机验证码没有或者过期
        if (code == null) {
            smsCode = StrUtils.getRandomString(6);
            // 4.2没有过期
        } else {
            // 4.2.1判断是否过重发时间
            Long oldTime = Long.parseLong(code.toString().split(":")[1]);
            if ((System.currentTimeMillis() - oldTime) < 60 * 1000) {
                throw new BusinessException("请勿频繁操作，请稍后重试！");
            }
            // 4.2.2过了重发时间
            smsCode = code.toString().split(":")[0];
        }
        // 5.将手机验证码保存到redis
        redisTemplate.opsForValue().set("register:" + phone, smsCode + ":" + System.currentTimeMillis(), 3, TimeUnit.MINUTES);
        // 6.调用工具类发送手机验证码
//        SmsUtils.sendSms(phone,"您的验证码是：" + smsCode + ",请在3分钟内使用！");
        // 直接打印测试
        System.out.println("您的验证码是：" + smsCode +"，请在3分钟内使用！");
    }

    @Override
    public void emailCode(SmsCodeDto smsCodeDto) throws MessagingException {
        // 1.校验是否为空
        String email = smsCodeDto.getEmail();
        if (StringUtils.isEmpty(email)) {
            throw new BusinessException("邮箱不能为空！");
        }
        // 2.校验邮箱是否已经被注册过
        User userMapperByEmail = userMapper.findByEmail(email);
        if (userMapperByEmail != null) {
            throw new BusinessException("该邮箱已被注册，请直接登录！");
        }
        // 3.获取邮箱验证码
        Object codeObj = redisTemplate.opsForValue().get("register:" + email);
        String emailCode = null;
        // 3.1邮箱验证码没有或者过期
        if (codeObj == null) {
            emailCode = StrUtils.getRandomString(6);
            // 3.2没有过期
        } else {
            // 3.2.1判断是否过重发时间
            Long oldTime = Long.parseLong(codeObj.toString().split(":")[1]);
            if ((System.currentTimeMillis() - oldTime) < 60 * 1000) {
                throw new BusinessException("请勿频繁操作，请稍后重试！");
            }
            // 3.2.2过了重发时间
            emailCode = codeObj.toString().split(":")[0];
        }
        // 4.将手机验证码保存到redis
        redisTemplate.opsForValue().set("register:" + email, emailCode + ":" + System.currentTimeMillis(), 3, TimeUnit.MINUTES);
        // 5.给邮箱发注册的通知
        MimeMessage message = javaMailSender.createMimeMessage();
        MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
        helper.setFrom("1827986361@qq.com");
        helper.setSubject("宠物乐园");
        helper.setText("<h1>您的注册验证码是：</h1>" + emailCode,true);
        helper.setTo(email);
        javaMailSender.send(message);
        // 直接打印测试
        System.out.println("您的验证码是：" + emailCode +"，请在3分钟内使用！");
    }

    @Override
    public void binderSmsCode(SmsCodeDto smsCodeDto) {
        // 1.校验是否为空
        String phone = smsCodeDto.getPhone();
        if (StringUtils.isEmpty(phone)) {
            throw new BusinessException("电话号码不能为空！");
        }
        // 3.校验手机号码是否注册过
        User user = userMapper.findByPhone(phone);
        if (user != null) {
            throw new BusinessException("手机号码已被注册，请直接登录！");
        }
        // 4.获取手机验证码
        Object code = redisTemplate.opsForValue().get("binder:" + phone);
        String smsCode = null;
        // 4.1手机验证码没有或者过期
        if (code == null) {
            smsCode = StrUtils.getRandomString(6);
            // 4.2没有过期
        } else {
            // 4.2.1判断是否过重发时间
            Long oldTime = Long.parseLong(code.toString().split(":")[1]);
            if ((System.currentTimeMillis() - oldTime) < 60 * 1000) {
                throw new BusinessException("请勿频繁操作，请稍后重试！");
            }
            // 4.2.2过了重发时间
            smsCode = code.toString().split(":")[0];
        }
        // 5.将手机验证码保存到redis
        redisTemplate.opsForValue().set("binder:" + phone, smsCode + ":" + System.currentTimeMillis(), 3, TimeUnit.MINUTES);
        // 6.调用工具类发送手机验证码
//        SmsUtils.sendSms(phone,"您的验证码是：" + smsCode + ",请在3分钟内使用！");
        // 直接打印测试
        System.out.println("您的验证码是：" + smsCode +"，请在3分钟内使用！");
    }
}
